﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;

//added
using System.IO.IsolatedStorage;
using System.IO;
using Microsoft.Phone.Notification;
using System.Collections.ObjectModel;

namespace Paw.Phone.PivotContent
{
    public partial class PushClientPage : PhoneApplicationPage
    {
        //Data members for this class

        //A unique ID for your phone, saved to internal memory
        Guid deviceID;

        //Add a reference to your deployed Push Service URL and name it ServiceReference1 and this line will compile.
        //In Solution Explorer, Right-click References, then click "Add Service Reference," then enter the URL for the SVC file 
        //for the Push Service and click "Go." Verify that the Push Service's four methods are indeed exposed then click "OK." 
        ServiceReference1.Service1Client myClient = new ServiceReference1.Service1Client();

        //URI for this app's notification channel.
        HttpNotificationChannel myPushChannel;

        // Constructor
        public PushClientPage()
        {
            InitializeComponent();

            //First, generate a GUID on this phone and save it; reuse if it exists to keep consistent with service's data.
            if (IsolatedStorageSettings.ApplicationSettings.Contains("DeviceId"))
            {
                //load existing
                deviceID = (Guid)IsolatedStorageSettings.ApplicationSettings["DeviceId"];
            }
            else
            {
                //generate new ID
                deviceID = Guid.NewGuid();
                IsolatedStorageSettings.ApplicationSettings["DeviceId"] = deviceID;
            }

            //Next, create a notification channel which will have its own URI that the web service will need to know.
            //We're naming the channel for this app "myChannel." Channels need only be created once per app; if the URI
            //ever changes, the ChannelUriUpdated event will fire. This event also fires when the channel is created for 
            //the first time.
            myPushChannel = HttpNotificationChannel.Find("myChannel");

            //check to see if this channel has already been created; if so, reuse
            if (myPushChannel == null)
            {
                rawmessage.Text += " Channel was null.";
                //This channel needs to be created. ChannelUriUpdated will fire upon completion.
                myPushChannel = new HttpNotificationChannel("myChannel"); //create, then attach delegates, then Open()
                attachHandlerFunctions();
                myPushChannel.Open(); // will not fire ChannelUriUpdated if no handler is wired up first!
            }
            else
            {
                rawmessage.Text += " Channel was found!";
                //ChannelUriUpdated is not going to fire. Call subscribing method on web service. Attach delegates.
                attachHandlerFunctions();
                myClient.SubscribeMyPhoneAsync(deviceID, myPushChannel.ChannelUri.ToString());
            }
        }

        void attachHandlerFunctions()
        {
            //attaches delegates to push channel events

            //if error, print onscreen
            myPushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(myPushChannel_ErrorOccurred);

            //After call to SubscribeMyPhone completes, notify of success
            myClient.SubscribeMyPhoneCompleted += new EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(myClient_SubscribeMyPhoneCompleted);
        
            //ChannelUriUpdated fires when channel is first created or the channel URI changes 
            myPushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(myPushChannel_ChannelUriUpdated);
        
            //Handle raw push notifications, which are received only while app is running.
            myPushChannel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(myPushChannel_HttpNotificationReceived);
        }

        void myPushChannel_HttpNotificationReceived(object sender, HttpNotificationEventArgs e)
        {
            //Fires from shell thread, so updates to UI have to use dispatcher's BeginInvoke() method.
            //The body of the notification is a stream, per the MPNS standard, but we know it's just text
            //per our web service design, so here we just decode, and display.
            Deployment.Current.Dispatcher.BeginInvoke(() => {
                //this will fire in UI thread
                StreamReader myReader = new StreamReader(e.Notification.Body);
                rawmessage.Text = "Received Raw Notification: " + myReader.ReadToEnd();
            });
        }

        void myPushChannel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
        {
            //also fires in notification thread. There are a couple things we want to do here, once we know we 
            //have a valid channel from MPNS. 
            // 1) Make sure phone's shell knows this channel is authorized to receive Tile updates when app is not running.
            if (myPushChannel.IsShellTileBound == false)
            {
                var ListOfAllowedDomains = new Collection<Uri> {
                    // Lists domains that can send tile updates and so forth as push notifications. 
                    // Only these authorized domains will be allowed by the shell to push new tiles to the phone
                    new Uri(@"http://127.0.0.1:81/") // e.g. if you published a webservice at http://foo.com/service1.svc -- put "http://foo.com" here.
                };

                //Register this channel with the shell, pass on authorized domain in way method expects
                myPushChannel.BindToShellTile(ListOfAllowedDomains);
            }

            //2) Make sure phone's shell knows this channel is authorized to receive Toast messages when app is not running
            if (myPushChannel.IsShellToastBound == false)
            {
                myPushChannel.BindToShellToast();
            }
            //3) Show that this event fired onscreen.
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                rawmessage.Text = "uri updated";
            });

            //4) Pass the new ChannelUri on to the subscription service.
            myClient.SubscribeMyPhoneAsync(deviceID, e.ChannelUri.ToString());
        }
   
        void myClient_SubscribeMyPhoneCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
        {
            //Handles completion of call to SubscribeMyPhone() on web service
            if (e.Error == null)
            {
                // no server-side error occurred
                subscriptionStatus.Text = "Subscribed!";
            }
            else
            {
                //show error onscreen
                subscriptionStatus.Text = e.Error.Message;
            }

            //As a last step, since we know at this point that we will have a valid ChannelUri, print its value onscreen.
            //Don't do this in real life, obviously. Here, it's just to show how MPNS works.
            channelURITextBlock.Text = myPushChannel.ChannelUri.ToString();
        }

        void myPushChannel_ErrorOccurred(object sender, NotificationChannelErrorEventArgs e)
        {
            //handles channel error caused from indirect exception
            subscriptionStatus.Text = e.Message;
        }
    }
}
